import JJRequestInfo from './JJRequestInfo'
import JJBaseRequest from './JJBaseRequest'
import { JJUtil, JJLog, JJCrypt, JJDeviceUtil, JJNotification } from './../util/index'
import { JJConfigHelper } from './../bizUtil/index.js';
import JJAPPConfig from './../resource/file/appConfig/JJAPPConfig'
import { hexMD5 } from './../thirdparty/index'

const g_cacheIv = 'qwe123!@'
const g_cryptKey = 'rty456$%'

export default class JJRequest extends JJBaseRequest {

    serviceName = null // no used now
    userCacheDirectory = null // no used now

    identity = ''
    isEncryption = false
    isSaveToDisk = false
    parametersForSavedFileName = null
    sensitiveDataForSavedFileName = null

    dataStorageWay = JJRequest.DataStorageWayLocalStorage
    static DataStorageWaySessionStorage = '01'
    static DataStorageWayLocalStorage = '02'

    constructor(identity, parameters, isEncryption, isSaveToDisk) {
        super()

        this.identity = identity;
        this.parameters = parameters;
        this.isEncryption = isEncryption;
        this.isSaveToDisk = isSaveToDisk;

        this.otherInfo.parameters = parameters

        // todo jj should set sensitiveDataForSavedFileName to user login id if possible
    }

    getHostUrl() {
        const host = JJConfigHelper.serverHostWithIdentity(this.identity)
        return host
    }

    getPathUrl() {
        const path = JJConfigHelper.serverPathWithIdentity(this.identity)
        return path
    }

    requestParameter() {
        // todo jj write http parameter following server interface
        let requestParameter = {}
        return requestParameter
    }

    postResponseNotification(isNetworkSuccess, isBusinessSuccess, response, errorObj, otherInfo) {
        let info = { isNetworkSuccess, isBusinessSuccess, response, errorObj, otherInfo }
        JJNotification.postNotificationName(this.identity, info)
    }

    requestCompleteFilter(response) {
        response = this.processResponse(response)

        this.otherInfo.responseData = response

        if (this.successForBusiness(response) && this.isSaveToDisk) {
            const oldObject = this.obtainCache()
            let newObject = this.filterSuccessCallBackValue(true, response)
            newObject = this.operation(oldObject, newObject)

            this.saveObjectToCache(newObject);
        }

        this.processAbnormalStatus(response)

        return Promise.resolve(response);
    }

    processResponse(response) {
        // todo jj write your code
        return response
    }

    processAbnormalStatus(response) {
        // todo jj process login timeout ...
    }

    successForBusiness(response) {
        // todo jj write code to judge if business success
        const success = true
        return success;
    }

    operation(oldObj, newObj) {
        return newObj
    }

    getCacheKey() {
        let keyStr = JJAPPConfig.channelName

        if (JJUtil.isNull(this.sensitiveDataForSavedFileName)) {
            keyStr = keyStr + '_'
        } else {
            keyStr = keyStr + this.sensitiveDataForSavedFileName + '_'
        }

        keyStr = keyStr + this.identity + '_'

        if (JJUtil.isNull(this.parametersForSavedFileName)) {
            keyStr = keyStr + JSON.stringify(this.parameters)
        } else {
            keyStr = keyStr + JSON.stringify(this.parametersForSavedFileName)
        }

        let value = hexMD5(keyStr)
        if (!JJAPPConfig.isStorageCrypt) {
            value = keyStr
        }

        return value ? value : keyStr
    }

    obtainCache() {
        const keyStr = this.getCacheKey()
        const value = this.__getItem(keyStr)
        if (JJUtil.isNull(value) || value.length <= 0) {
            return null
        }

        if (!JJAPPConfig.isStorageCrypt) {
            try {
                const obj = JSON.parse(value)
                if (JJUtil.isNull(obj)) {
                    return value
                } else {
                    return obj
                }
            } catch (error) {
                return value
            }
        }

        const cryptKey = g_cryptKey
        let decrypted = ''
        try {
            decrypted = JJCrypt.aesDecrypt(value, cryptKey, g_cacheIv)
            const obj = JSON.parse(decrypted)
            if (JJUtil.isNull(obj)) {
                return decrypted
            } else {
                return obj
            }
        } catch (error) {
            return decrypted
        }
    }

    saveObjectToCache(obj) {
        if (JJUtil.isNull(obj)) {
            return
        }

        if ('object' == typeof (obj)) {
            obj = JSON.stringify(obj)
        }

        const keyStr = this.getCacheKey()
        const cryptKey = g_cryptKey

        const encrypted = JJCrypt.aesEncrypt(obj, cryptKey, g_cacheIv)

        if (!JJAPPConfig.isStorageCrypt) {
            this.__setItem(keyStr, obj)
        } else {
            this.__setItem(keyStr, encrypted)
        }
    }

    removeCache() {
        const keyStr = this.getCacheKey()
        this.__removeItem(keyStr)
    }

    __getItem(key) {
        if (JJRequest.DataStorageWaySessionStorage === this.dataStorageWay) {
            return sessionStorage.getItem(key)
        } else {
            return localStorage.getItem(key)
        }
    }

    __setItem(key, value) {
        if (JJRequest.DataStorageWaySessionStorage === this.dataStorageWay) {
            sessionStorage.setItem(key, value)
        } else {
            localStorage.setItem(key, value)
        }
    }

    __removeItem(key) {
        if (JJRequest.DataStorageWaySessionStorage === this.dataStorageWay) {
            sessionStorage.removeItem(key)
        } else {
            localStorage.removeItem(key)
        }
    }

    toString() {
        const para = this.parameters
        let msg = '【Request】 url: ' + this.buildRequestUrl()
        msg = msg + '\r\n=================================> parameter: ' + JSON.stringify(para)
        msg = msg + '\r\n==================================> deviceNo: ' + JJDeviceUtil.getDeviceNo()
        return msg
    }
}
